import WxPay from 'wechatpay-node-v3';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as crypto from 'crypto';

export interface WechatCreatePaymentParams {
  outTradeNo: string;
  totalAmount: number;
  description: string;
  timeExpire?: Date;
  attach?: string;
  goodsTag?: string;
  openid?: string; // JSAPI支付需要
}

@Injectable()
export class WechatPayService {
  private pay: WxPay;
  private wechatConfig: any;

  constructor(private readonly configService: ConfigService) {
    try {
      // 从配置中读取微信支付配置
      this.wechatConfig = this.configService.get('payment.wechat');

      // 检查配置是否存在
      if (!this.wechatConfig) {
        console.warn('⚠️ 微信支付配置未设置，跳过初始化');
        return;
      }

      console.log('🔍 微信支付配置:', {
        hasAppId: !!this.wechatConfig.appId,
        hasMchId: !!this.wechatConfig.mchId,
        hasSerialNo: !!this.wechatConfig.serialNo,
        hasPublicKey: !!this.wechatConfig.publicKey,
        hasPrivateKey: !!this.wechatConfig.privateKey,
        hasApiV3Key: !!this.wechatConfig.apiV3Key,
      });

      this.pay = new WxPay({
        appid: this.wechatConfig.appId,
        mchid: this.wechatConfig.mchId,
        serial_no: this.wechatConfig.serialNo,
        publicKey: this.wechatConfig.publicKey,
        privateKey: this.wechatConfig.privateKey,
        key: this.wechatConfig.apiV3Key,
      });
      console.log('✅ 微信支付SDK初始化成功');
    } catch (error) {
      console.error('❌ 微信支付SDK初始化失败:', error);
      console.error('错误详情:', error?.message || error);
      // 不抛出错误，允许服务启动（支付功能将不可用）
      console.warn('⚠️ 微信支付功能将不可用');
    }
  }

  /**
   * 创建Native支付（二维码支付）
   */
  async createNativePay(
    params: WechatCreatePaymentParams,
  ): Promise<{ codeUrl: string }> {
    try {
      const paymentData = {
        appid: this.wechatConfig.appId,
        mchid: this.wechatConfig.mchId,
        description: params.description,
        out_trade_no: params.outTradeNo,
        time_expire: params.timeExpire?.toISOString(),
        attach: params.attach,
        notify_url: this.wechatConfig.notifyUrl,
        amount: {
          total: Math.round(params.totalAmount * 100), // 转换为分
          currency: 'CNY',
        },
      };

      console.log(
        '\x1b[32m📱 调用微信支付API，参数:\x1b[0m',
        JSON.stringify(paymentData, null, 2),
      );

      const result: any = await this.pay.transactions_native(paymentData);

      console.log('\x1b[32m✅ 微信API返回结果:\x1b[0m', JSON.stringify(result, null, 2));

      // 微信SDK返回的数据在 result.data 中
      const code_url = result.data?.code_url || result.code_url;
      console.log('\x1b[32m🔑 提取的code_url:\x1b[0m', code_url);

      if (!code_url) {
        console.error('❌ 微信支付返回数据中没有code_url字段！');
        console.error('完整返回数据:', result);
      }

      return {
        codeUrl: code_url || '',
      };
    } catch (error) {
      console.error('❌ 微信Native支付创建失败:', error);
      console.error('错误详情:', JSON.stringify(error, null, 2));
      throw new Error('微信Native支付创建失败');
    }
  }

  /**
   * 创建H5支付
   */
  async createH5Pay(
    params: WechatCreatePaymentParams & {
      sceneInfo: {
        payer_client_ip: string;
        h5_info: {
          type: string;
          app_name?: string;
          app_url?: string;
          bundle_id?: string;
          package_name?: string;
        };
      };
    },
  ): Promise<{ h5Url: string }> {
    try {
      const paymentData = {
        appid: this.wechatConfig.appId,
        mchid: this.wechatConfig.mchId,
        description: params.description,
        out_trade_no: params.outTradeNo,
        time_expire: params.timeExpire?.toISOString(),
        attach: params.attach,
        notify_url: this.wechatConfig.notifyUrl,
        amount: {
          total: Math.round(params.totalAmount * 100), // 转换为分
          currency: 'CNY',
        },
        scene_info: params.sceneInfo,
      } as any;

      const result: any = await this.pay.transactions_h5(paymentData);

      console.log('微信H5支付创建成功:', params.outTradeNo);
      return {
        h5Url: result.h5_url,
      };
    } catch (error) {
      console.error('微信H5支付创建失败:', error);
      throw new Error('微信H5支付创建失败');
    }
  }

  /**
   * 创建JSAPI支付（小程序/公众号支付）
   */
  async createJsapiPay(params: WechatCreatePaymentParams): Promise<{
    appId: string;
    timeStamp: string;
    nonceStr: string;
    package: string;
    signType: string;
    paySign: string;
  }> {
    try {
      if (!params.openid) {
        throw new Error('JSAPI支付需要openid');
      }

      const paymentData = {
        appid: this.wechatConfig.appId,
        mchid: this.wechatConfig.mchId,
        description: params.description,
        out_trade_no: params.outTradeNo,
        time_expire: params.timeExpire?.toISOString(),
        attach: params.attach,
        notify_url: this.wechatConfig.notifyUrl,
        amount: {
          total: Math.round(params.totalAmount * 100), // 转换为分
          currency: 'CNY',
        },
        payer: {
          openid: params.openid,
        },
      };

      const result: any = await this.pay.transactions_jsapi(paymentData);

      // 生成小程序支付参数
      const prepayId = result.prepay_id;
      const timeStamp = Math.floor(Date.now() / 1000).toString();
      const nonceStr = crypto.randomBytes(16).toString('hex');
      const packageStr = `prepay_id=${prepayId}`;

      // 生成签名
      const paySign = this.generatePaySign({
        appId: this.wechatConfig.appId,
        timeStamp,
        nonceStr,
        package: packageStr,
        signType: 'RSA',
      });

      console.log('微信JSAPI支付创建成功:', params.outTradeNo);
      return {
        appId: this.wechatConfig.appId,
        timeStamp,
        nonceStr,
        package: packageStr,
        signType: 'RSA',
        paySign,
      };
    } catch (error) {
      console.error('微信JSAPI支付创建失败:', error);
      throw new Error('微信JSAPI支付创建失败');
    }
  }

  /**
   * 查询订单
   */
  async queryOrder(outTradeNo: string): Promise<any> {
    try {
      const result = await this.pay.query({
        out_trade_no: outTradeNo,
      });

      // 微信SDK返回格式：{ status: 200, data: {...} }
      // 我们只返回 data 部分
      return result.data || result;
    } catch (error) {
      console.error('微信订单查询失败:', error);
      throw new Error('微信订单查询失败');
    }
  }

  /**
   * 关闭订单
   */
  async closeOrder(outTradeNo: string): Promise<any> {
    try {
      const result = await this.pay.close(outTradeNo);

      return result;
    } catch (error) {
      console.error('微信订单关闭失败:', error);
      throw new Error('微信订单关闭失败');
    }
  }

  /**
   * 申请退款
   */
  async refund(params: {
    outTradeNo: string;
    outRefundNo: string;
    refundAmount: number;
    totalAmount: number;
    reason?: string;
  }): Promise<any> {
    try {
      const refundData = {
        out_trade_no: params.outTradeNo,
        out_refund_no: params.outRefundNo,
        reason: params.reason || '用户申请退款',
        amount: {
          refund: Math.round(params.refundAmount * 100), // 转换为分
          total: Math.round(params.totalAmount * 100), // 转换为分
          currency: 'CNY',
        },
        notify_url: this.wechatConfig.notifyUrl.replace(
          '/notify',
          '/refund-notify',
        ),
      };

      const result = await this.pay.refunds(refundData);

      return result;
    } catch (error) {
      console.error('微信退款失败:', error);
      throw new Error('微信退款失败');
    }
  }

  /**
   * 处理微信支付回调
   */
  async handleNotify(
    headers: any,
    body: any,
  ): Promise<{
    isValid: boolean;
    outTradeNo?: string;
    tradeState?: string;
    transactionId?: string;
    totalAmount?: number;
    paidAt?: Date;
  }> {
    try {
      // 验证签名
      const isValid = this.verifySign(headers, body);

      if (!isValid) {
        console.error('微信支付回调签名验证失败');
        return { isValid: false };
      }

      console.log('🔍 微信支付回调body.resource:', body.resource);

      // 解密数据
      const decryptedData = this.decryptData(body.resource);

      // 打印解密后的完整数据用于调试
      console.log(
        '🔍 解密后的原始数据:',
        JSON.stringify(decryptedData, null, 2),
      );

      const {
        out_trade_no: outTradeNo,
        trade_state: tradeState,
        transaction_id: transactionId,
        amount,
        success_time,
      } = decryptedData;

      console.log('微信支付回调处理成功:', {
        outTradeNo,
        tradeState,
        transactionId,
        totalAmount: amount?.total,
      });

      return {
        isValid: true,
        outTradeNo,
        tradeState,
        transactionId,
        totalAmount: amount?.total ? amount.total / 100 : undefined, // 转换为元
        paidAt: success_time ? new Date(success_time) : undefined,
      };
    } catch (error) {
      console.error('微信支付回调处理失败:', error);
      return { isValid: false };
    }
  }

  /**
   * 验证微信支付回调签名
   */
  private verifySign(headers: any, body: any): boolean {
    try {
      const {
        'wechatpay-signature': signature,
        'wechatpay-timestamp': timestamp,
        'wechatpay-nonce': nonce,
        'wechatpay-serial': serial,
      } = headers;

      if (!signature || !timestamp || !nonce || !serial) {
        console.error('微信支付回调缺少必要的头部信息');
        return false;
      }

      // 构建验签字符串
      const signStr = `${timestamp}\n${nonce}\n${JSON.stringify(body)}\n`;

      // 使用公钥验证签名
      const verify = crypto.createVerify('RSA-SHA256');
      verify.update(signStr, 'utf8');

      return verify.verify(this.wechatConfig.publicKey, signature, 'base64');
    } catch (error) {
      console.error('微信支付签名验证失败:', error);
      return false;
    }
  }

  /**
   * 解密微信支付回调数据
   * 使用 wechatpay-node-v3 库的标准方法
   */
  private decryptData(resource: any): any {
    try {
      const { algorithm, ciphertext, associated_data, nonce } = resource;

      if (algorithm !== 'AEAD_AES_256_GCM') {
        throw new Error('不支持的加密算法');
      }

      // 直接使用 wechatpay-node-v3 库的解密方法
      const decryptedBuffer: any = this.pay.decipher_gcm(
        ciphertext,
        associated_data,
        nonce,
        this.wechatConfig.apiV3Key,
      );
      console.log('🔍 解密后的Buffer:', decryptedBuffer);

      return decryptedBuffer;
    } catch (error) {
      console.error('微信支付数据解密失败:', error);
      console.error('解密参数:', {
        algorithm: resource.algorithm,
        nonce_length: resource.nonce?.length,
        ciphertext_length: resource.ciphertext?.length,
        associated_data: resource.associated_data,
        apiV3Key_length: this.wechatConfig.apiV3Key?.length,
      });
      throw new Error('微信支付数据解密失败');
    }
  }

  /**
   * 生成支付签名
   */
  private generatePaySign(params: {
    appId: string;
    timeStamp: string;
    nonceStr: string;
    package: string;
    signType: string;
  }): string {
    const signStr = `${params.appId}\n${params.timeStamp}\n${params.nonceStr}\n${params.package}\n`;

    const sign = crypto.createSign('RSA-SHA256');
    sign.update(signStr, 'utf8');

    return sign.sign(this.wechatConfig.privateKey, 'base64');
  }

  /**
   * 获取支付配置信息（用于前端）
   */
  getPaymentConfig() {
    return {
      appId: this.wechatConfig.appId,
      // 不返回敏感信息
    };
  }
}




